package com.umeox.watch.moto.apiclient.http;

import android.text.TextUtils;
import android.util.Log;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.umeox.moto.common.log.Logger;
import com.umeox.moto.common.utils.FileUtils;
import com.umeox.watch.moto.apiclient.http.adapter.HttpsHelp;
import com.umeox.watch.moto.apiclient.http.callback.WaasCallback;
import com.umeox.watch.moto.apiclient.http.client.APIClientFactory;
import com.umeox.watch.moto.apiclient.http.client.APIClientImpl;
import com.umeox.watch.moto.apiclient.http.request.WaasRequest;
import com.umeox.watch.moto.apiclient.http.request.WaasRequestBuilder;
import com.umeox.watch.moto.apiclient.http.response.WaasResponse;
import com.umeox.watch.moto.apiclient.http.response.WaasResponseImpl;
import com.umeox.watch.moto.apiclient.model.FileSignDTO;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import okhttp3.Call;
import okhttp3.ConnectionPool;
import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;

public class FileApiWrapper {
    private APIClientImpl apiClient;
    private HostRedirect redirectImpl;
    private OkHttpClient okHttpClient;

    private FileApiWrapper() {
    }

    private OkHttpClient getOkHttpClient() {
        if (okHttpClient == null) {
            HttpsHelp.SSLParams params = HttpsHelp.getTlsSocketFactory();
            ConnectionPool pool = new ConnectionPool(5, 30, TimeUnit.SECONDS);
            OkHttpClient.Builder okHttpClientBuilder = new OkHttpClient.Builder()
                    .connectTimeout(30, TimeUnit.SECONDS)
                    .writeTimeout(30, TimeUnit.SECONDS)
                    .readTimeout(30, TimeUnit.SECONDS)
                    .callTimeout(30, TimeUnit.SECONDS)
                    .sslSocketFactory(params.sSLSocketFactory, params.trustManager)
                    .hostnameVerifier(params.hostnameVerifier)
                    .connectionPool(pool);
            okHttpClient = okHttpClientBuilder.build();
        }
        return okHttpClient;
    }

    public static FileApiWrapper getInstance() {
        return InstanceHolder.INSTANCE;
    }

    public void setHostRedirect(HostRedirect hostRedirect) {
        this.redirectImpl = hostRedirect;
    }

    public void init(APIClientImpl.InitializeConfig config) {
        if (InstanceHolder.initialized) {
            throw new RuntimeException("can not duplicated initialize !");
        } else {
            apiClient = (APIClientImpl) APIClientFactory.getFileApiClient();
            apiClient.init(config);
            InstanceHolder.initialized = true;
        }
    }

    public boolean downloadFile(String url, File file) {
        if (TextUtils.isEmpty(url) || !url.startsWith("http")) {
            throw new IllegalArgumentException("invalid url");
        }
        if (file == null) {
            throw new IllegalArgumentException("'file' cannot be null");
        }

        OkHttpClient okHttpClient = getOkHttpClient();
        Request request = new Request.Builder().url(url).build();
        Call call = okHttpClient.newCall(request);
        Response response = null;
        try {
            response = call.execute();
            if (response.code() == 200 && response.body() != null) {
                try {
                    readData(file, response.body().bytes());
                    return true;
                } catch (Exception e) {
                    e.printStackTrace();
                }

            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (response != null) {
                response.close();
            }
//            okHttpClient.connectionPool().evictAll();
        }
        return false;
    }

    public void downloadFile(final String url, final File file, final WaasCallback callback) {
        if (TextUtils.isEmpty(url) || !url.startsWith("http")) {
            throw new IllegalArgumentException("invalid url");
        }
        if (file == null) {
            throw new IllegalArgumentException("'file' cannot be null");
        }
        apiClient.send(new WaasRequestBuilder().setHost(url).build(), new WaasCallback() {
            @Override
            public void onFailure(WaasRequest request, Exception e) {
                if (callback != null) {
                    callback.onFailure(request, e);
                }
            }

            @Override
            public void onResponse(WaasRequest request, WaasResponse response) {
                WaasResponseImpl waasResponse = new WaasResponseImpl();
                waasResponse.setCode(response.getCode());
                waasResponse.setMessage(response.getMessage());
                if (waasResponse.isSuccessful()) {
                    try {
                        readData(file, response.getRawData());
                        waasResponse.setData(true);
                    } catch (Exception e) {
                        waasResponse.setCode(-1);
                        waasResponse.setData(false);
                        waasResponse.setMessage(e.getMessage());
                    }
                }
                if (callback != null) {
                    callback.onResponse(request, waasResponse);
                }
            }
        });
    }

    private void readData(File file, byte[] data) throws Exception {
        FileOutputStream fos = null;
        //储存下载文件的目录
        try {
            if (!file.getParentFile().exists()) {
                FileUtils.createFolder(file.getParentFile().getPath());
                Log.w("FileApi", "parent file [" + file.getParentFile().getPath() + "] is not exists, creates a new");
            }
            if (!file.exists()) {
                file.createNewFile();
            }
            fos = new FileOutputStream(file);
            fos.write(data);
            fos.flush();
        } finally {
            try {
                if (fos != null) {
                    fos.close();
                }
            } catch (IOException ignored) {
            }
        }
    }

    public String uploadFile(File file) {
        Map<String, Object> param = new HashMap<>();
        param.put("token", "app01");
        param.put("file", file);
        WaasRequest request = new WaasRequestBuilder()
                .setHost(getHost())
                .setApi(ApiEnum.UPLOAD_FILE)
                .setParas(param).build();
        WaasResponse response = apiClient.send(request);
        if (response.isSuccessful() && response.getRawData() != null) {
            JSONObject result = JSON.parseObject(new String(response.getRawData(), StandardCharsets.UTF_8));
            if (result != null) {
                return result.getString("file");
            }
        }
        return "";
    }

    public String uploadSOSFile(FileSignDTO fileSignDTO, String fileName,File file) {

        String key = fileSignDTO.folder + "/" + fileName;
        String url = (fileSignDTO.secure ? "https://" : "http://") + fileSignDTO.endPoint + ":" + fileSignDTO.port + fileSignDTO.uri;
        OkHttpClient okHttpClient = getOkHttpClient();
        RequestBody requestBody = RequestBody.create(MediaType.parse("application/octet-stream"), file);//创建requestBody对象
        MultipartBody multipartBody = new MultipartBody.Builder()
                .setType(MultipartBody.FORM)
                .addFormDataPart("key", key)
                .addFormDataPart("acl", fileSignDTO.acl)
                .addFormDataPart("X-Amz-Credential", fileSignDTO.credential)
                .addFormDataPart("X-Amz-Algorithm", fileSignDTO.algorithm)
                .addFormDataPart("X-Amz-Date", fileSignDTO.date)
                .addFormDataPart("Policy", fileSignDTO.policy)
                .addFormDataPart("X-Amz-Signature", fileSignDTO.signature)
                .addFormDataPart("success_action_status", "200")
                .addFormDataPart("file", fileName, requestBody)
                .build();
        Request request = new Request.Builder().url(url).post(multipartBody).build();
        Call call = okHttpClient.newCall(request);
        Response response = null;
        Logger.e("uploadSOSFile", "url=" + url + ",key=" + key);
        try {
            response = call.execute();
            Logger.e("uploadSOSFile", "response code:" + response.code());

            switch (response.code()) {
                case 200:
                    return TextUtils.isEmpty(response.header("Location")) ? (url + "/" + key) : response.header("Location");
                case 400:
                    return "请求参数错误";
                case 403:
                    return "签名错误，Policy已过期";
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (response != null) {
                response.close();
            }
            if(file.getAbsolutePath().startsWith(FileUtils.getCompressImageCache())){
                FileUtils.deleteFile(file.getAbsoluteFile());
            }
//            okHttpClient.connectionPool().evictAll();
        }
        return "";
    }

    public void uploadFile(File file, final WaasCallback callback) {
        Map<String, Object> param = new HashMap<>();
        param.put("token", "app01");
        param.put("file", file);
        WaasRequest request = new WaasRequestBuilder()
                .setHost(getHost())
                .setApi(ApiEnum.UPLOAD_FILE)
                .setParas(param).build();
        apiClient.send(request, new WaasCallback() {
            @Override
            public void onFailure(WaasRequest request, Exception e) {
                if (callback != null) {
                    callback.onFailure(request, e);
                }
            }

            @Override
            public void onResponse(WaasRequest request, WaasResponse response) {
                WaasResponseImpl waasResponse = new WaasResponseImpl();
                waasResponse.setCode(response.getCode());
                waasResponse.setMessage(response.getMessage());
                if (response.isSuccessful()) {
                    try {
                        waasResponse.setData(JSON.parseObject(new String(response.getRawData(), StandardCharsets.UTF_8)).getString("file"));
                    } catch (Exception e) {
                        waasResponse.setCode(-1);
                        waasResponse.setMessage(e.getMessage());
                    }
                }
                if (callback != null) {
                    callback.onResponse(request, waasResponse);
                }
            }
        });
    }

    private String getHost() {
        if (redirectImpl != null) {
            return redirectImpl.getHost();
        }
        return "";
    }

    public interface HostRedirect {
        String getHost();
    }

    private static class InstanceHolder {
        private static final FileApiWrapper INSTANCE = new FileApiWrapper();
        private static boolean initialized = false;
    }
}
